/**************************************************************************************************
	$Header: /pub/cvsroot/mydns/src/mydns/named.h,v 1.6 2002/07/07 06:16:59 bboy Exp $

	Copyright (C) 2002  Don Moore <bboy@bboy.net>

	This program is free software; you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation; either version 2 of the License, or
	(at Your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program; if not, write to the Free Software
	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
**************************************************************************************************/

#ifndef _MYNAMED_H
#define _MYNAMED_H

#include "mydnsutil.h"
#include "header.h"
#include "mydns.h"
#include "bits.h"
#include "cache.h"
#include "status.h"

#if HAVE_SYS_RESOURCE_H
#	include <sys/resource.h>
#endif

#if HAVE_NETDB_H
#	include <netdb.h>
#endif


/* The alarm function runs every ALARM_INTERVAL seconds */
#define	ALARM_INTERVAL		5

#define	DNS_MAXPACKETLEN	DNS_MAXPACKETLEN_UDP

/* Maximum CNAME recursion depth */
#define	DNS_MAX_CNAME_RECURSION	25

/* Size of reply header data; that's id + DNS_HEADER + qdcount + ancount + nscount + arcount */
#define	DNS_HEADERSIZE		(SIZE16 * 6)

/* If debugging malloc, use malloc and friends instead of wrappers */
#if MTRACE_ENABLED
#	define	MALLOC	malloc
#	define	REALLOC	realloc
#	define	CALLOC	calloc
#	define	STRDUP	strdup
#else
#	define	MALLOC	xmalloc
#	define	REALLOC	xrealloc
#	define	CALLOC	xcalloc
#	define	STRDUP	xstrdup
#endif	/* !MTRACE_ENABLED */

/* Receive type */
typedef enum _tasksocktype_t
{
	SOCKTYPE_UDP = 0,
	SOCKTYPE_TCP
} tasksocktype_t;

/* Task status flags */
typedef enum _taskstat_t
{
	NEED_ANSWER = 0,	/* We need to find the ANSWER */
	NEED_SEND			/* We need to write the request to the client */
} taskstat_t;


/* Sections in reply */
typedef enum _datasection_t
{
	ANSWER, AUTHORITY, ADDITIONAL
} datasection_t;


/* RR: A single resource record (of any supported type) */
typedef struct _named_rr
{
	dns_rrtype_t	rrtype;			/* Record type (what table this data came from) */
	u_int32_t		id;				/* ID associated with RR */
	u_char			name[DNS_MAXNAMELEN];	/* Name to send with reply */
	off_t				offset;			/* The offset within the reply data (t->rdata) */
	size_t			length;			/* The length of data within the reply */
	void				*rr;				/* The RR data */
	struct _named_rr *next;			/* Pointer to the next item */
} RR;

/* RRLIST: A list of resource records */
typedef struct _named_rrlist
{
	size_t size;						/* Count of records */
	RR *head;							/* Head of list */
	RR *tail;							/* Tail of list */
} RRLIST;


/* TASK: DNS query task */
typedef struct _named_task
{
	u_int64_t	internal_id;									/* Internal task ID */
	taskstat_t	status;											/* Current status of query */
	int			fd;												/* Socket FD */
	time_t		timeout;											/* Time task expires (timeout) */
	tasksocktype_t	socktype;									/* Type of socket (TCP or UDP) */
	struct sockaddr_in addr;									/* Address of client */

	/* Query information */
	u_int16_t	id;												/* Query ID */
	DNS_HEADER  hdr;												/* Header */
	dns_qtype_t	qtype;											/* Query type */
	u_char		qname[DNS_MAXNAMELEN];						/* Query name object */

	NUMLIST		*Cnames;											/* Array of CNAMEs found */

	u_char		*qd;												/* Question section data */
	size_t		qdlen;											/* Size of question section */
	u_int16_t	qdcount;											/* "qdcount", from header field */

	u_char		**Names;											/* Names stored in reply */
	u_int			*Offsets;										/* Offsets for names */
	u_int			numNames;										/* Number of names in the list */

	RRLIST		an, ns, ar;										/* RR's for ANSWER, AUTHORITY, ADDITIONAL */

	u_char		*rdata;											/* Header portion of reply */
	size_t		rdlen;											/* Length of `rdata' */

	u_char		*reply;											/* Total constructed reply data */
	size_t		replylen;										/* Length of `reply' */

	struct _named_task *prev, *next;							/* Pointers to previous/next rec in queue */
} TASK;


/* Queue structure for TASK records (really not a queue, but a list) */
typedef struct _named_queue
{
	size_t size;													/* Number of elements in queue */
	TASK	*head;													/* Pointer to first element in list */
	TASK	*tail;													/* Pointer to last element in list */
} QUEUE;



/* Global variables */
extern CONF		 *Conf;											/* Config file data */
extern MYSQL	 *mysql;											/* MySQL database connection */
extern QUEUE	 *Tasks;											/* Task queue */
extern CACHE	 *Cache;											/* Zone cache */
extern time_t	 current_time;									/* Current time */
extern int		 exit_after_one;								/* Answer one query, then exit? */


extern void load_config(), dump_config(), output_create_tables();								/* conf.c */

extern MYDNS_SOA	*find_soa(TASK *, u_char *, u_char *);											/* data.c */
extern MYDNS_RR	*find_rr(TASK *, u_int32_t, dns_qtype_t, u_char *);						/* data.c */
extern MYDNS_PTR	*find_ptr(TASK *, u_char *);														/* data.c */

extern void name_remember(TASK *, u_char *, u_int);												/* encode.c */
extern u_int name_find(TASK *, u_char *);																/* encode.c */
extern u_char *name_unencode(u_char *, size_t, u_char *, u_char *, size_t);				/* encode.c */
extern int	name_encode(TASK *, u_char *, u_char *, u_int);										/* encode.c */

extern int dnserror(TASK *, dns_rcode_t);																/* error.c */

extern QUEUE *queue_init(void);																			/* queue.c */
extern void	enqueue(QUEUE *, TASK *);																	/* queue.c */
extern void	dequeue(QUEUE *, TASK *, int);															/* queue.c */

extern void reply_init(TASK *);																			/* reply.c */
extern void build_reply(TASK *);																			/* reply.c */

extern int resolve(TASK *, datasection_t, dns_qtype_t, u_char *);								/* res.c */

extern void rrlist_add(TASK *, datasection_t, dns_rrtype_t, void *, u_char *);			/* rr.c */
extern void rrlist_free(RRLIST *);																		/* rr.c */

extern void server_status(void);																			/* status.c */

extern void task_init_header(TASK *);																	/* task.c */
extern char	*desctask(TASK *);																			/* task.c */
extern TASK *task_init(taskstat_t, int, tasksocktype_t, struct sockaddr_in *);			/* task.c */
extern void task_free(TASK *);																			/* task.c */
extern void task_build_reply(TASK *);																	/* task.c */
extern TASK *task_process(TASK *);																		/* task.c */

extern int	read_udp_query(int);																			/* udp.c */
extern int	write_udp_reply(TASK *);																	/* udp.c */

#endif /* _MYNAMED_H */

/* vi:set ts=3: */
